﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

using Lidgren.Network;


namespace IMLibrary.NetClient  
{
    /// <summary>
    /// UDP网络客户端
    /// </summary>
    public class UDPClient
    {
        /// <summary>
        /// 构造
        /// </summary>
        public UDPClient()
        {
           
        }

        #region 属性
        private Lidgren.Network.NetClient s_client = null;
        private bool _IsConnect;
        /// <summary>
        /// 是否连接服务器
        /// </summary>
        public bool IsConnect
        {
            get
            {
                return _IsConnect;
            }
        }

        public string RemoteHost
        { set; get; }

        public int    RemotePort
        { set; get; }

        SendOrPostCallback CallGetMessage = null;
        
        #endregion

        #region 事件
        public delegate void  EventHandler(object sender, UDPEventArgs e);
        /// <summary>
        /// 客户端已联接事件
        /// </summary>
        public event EventHandler Connected;
        private void onConnected(UDPEventArgs e)
        {
            if (Connected != null)
                Connected(this, e);

        }
        /// <summary>
        /// 客户端联接断开事件
        /// </summary>
        public event EventHandler Disconnected;
        private void onDisconnected(UDPEventArgs e)
        {
            if (Disconnected != null)
                Disconnected(this, e);

        }
        /// <summary>
        /// 收到消息事件
        /// </summary>
        public event EventHandler RecivedMsg;
        private void onRecivedMsg(UDPEventArgs e)
        {
            if (RecivedMsg != null)
                RecivedMsg(this, e);
        }

        /// <summary>
        /// 收到未知消息事件
        /// </summary>
        public event EventHandler RecivedElseData;
        private void onRecivedElseData(UDPEventArgs e)
        {
            if (RecivedElseData != null)
                RecivedElseData(this, e);
        }
        /// <summary>
        /// 收到系统消息（警告、调试、错误等）事件
        /// </summary>
        public event EventHandler RecivedSystemMsg;
        private void onRecivedSystemMsg(UDPEventArgs e)
        {
            if (RecivedSystemMsg != null)
                RecivedSystemMsg(this, e);
        }
        #endregion

        #region 公共方法
        /// <summary>
        /// 连接主机
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        public void Connect(string host, int port)
        {
            NetPeerConfiguration config = new NetPeerConfiguration("OurMsg");
            config.AutoFlushSendQueue = false;
            if (s_client == null)
            {
                s_client = new  Lidgren.Network.NetClient(config);
                CallGetMessage = new SendOrPostCallback(GetMessage);
                s_client.RegisterReceivedCallback(CallGetMessage);
                s_client.Start();
            }
            RemoteHost = host;
            RemotePort = port;
            s_client.Connect(host, port);
        }

        /// <summary>
        /// 关闭套接字连接，并释放资源
        /// </summary>
        public void Disconnect()
        {
            if (s_client != null )
            {
                s_client.Disconnect(""); 
            }
        }

        /// <summary>
        /// 关闭套接字并释放资源
        /// </summary>
        public void Shutdown()
        {
            if (s_client != null)
            {
                if (CallGetMessage != null)
                    s_client.UnregisterReceivedCallback(CallGetMessage);
                s_client.Disconnect("");
                s_client.Shutdown(""); 
                s_client = null;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="text"></param>
        public void Send(string text)
        {
            Send(Encoding.UTF8.GetBytes(text)); 
        }

        public void Send(byte[] data)
        {
            NetOutgoingMessage om = s_client.CreateMessage();
            om.Write(data);
            s_client.SendMessage(om, NetDeliveryMethod.ReliableOrdered);
            s_client.FlushSendQueue();
        }
        #endregion
         
        #region 私有方法
        private void GetMessage(object peer)
        {
            NetIncomingMessage im;
            while (s_client!=null && (im = s_client.ReadMessage()) != null)
            {
                switch (im.MessageType)
                {
                    case NetIncomingMessageType.DebugMessage:
                    case NetIncomingMessageType.ErrorMessage:
                    case NetIncomingMessageType.WarningMessage:
                    case NetIncomingMessageType.VerboseDebugMessage:
                        onRecivedSystemMsg(new UDPEventArgs(false, new byte[0], null));
                        break;
                    case NetIncomingMessageType.StatusChanged:
                        NetConnectionStatus status = (NetConnectionStatus)im.ReadByte();
                        if (status == NetConnectionStatus.Disconnected)
                        {
                            _IsConnect = false;
                            onDisconnected(new UDPEventArgs(false, new byte[0], null));
                        }
                        else if (status == NetConnectionStatus.Connected)
                        {
                            _IsConnect = true;
                            onConnected(new UDPEventArgs(false, new byte[0], null));
                        }
                        break;
                    case NetIncomingMessageType.Data:
                        onRecivedMsg(new UDPEventArgs(false, im.ReadBytes(im.LengthBytes), null));
                        break;
                    default:
                        onRecivedElseData(new UDPEventArgs(false, im.ReadBytes(im.LengthBytes), null));
                        break;
                }
            }
        }
        #endregion

    }





}
